﻿using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace netCoreStudy.Entities.Base
{
	/// <summary>
	/// controller 基类
	/// </summary>
	/// <typeparam name="T">实体</typeparam>
	/// <typeparam name="TDto">向外展示dto</typeparam>
	/// <typeparam name="TParam">查询参数</typeparam>
	/// <typeparam name="TAddDto">添加的dto</typeparam>
	/// <typeparam name="TUpdateDto">更新的dto</typeparam>
	public abstract class BaseController<T, TDto, TParam, TAddDto, TUpdateDto> : ControllerBase
		where T : BaseEntity
		where TDto : BaseDto
		where TParam : BaseParameter
	{
		protected readonly ILogger<BaseController<T, TDto, TParam, TAddDto, TUpdateDto>> _logger;
		protected readonly IBaseService<T> _baseService;
		protected readonly IMapper _mapper;


		public BaseController(ILogger<BaseController<T, TDto, TParam, TAddDto, TUpdateDto>> logger,
			IBaseService<T> baseService,
			IMapper mapper
		)
		{
			_logger = logger;
			_baseService = baseService;
			_mapper = mapper;
		}

		/// <summary>
		/// 获取单个 
		/// </summary>
		/// <returns></returns>
		[HttpGet("{id}")]
		//[Authorize("Permission")]
		public virtual async Task<IActionResult> GetOne(
			long id)
		{
			T t = await _baseService.GetOneByIdAsync(id);
			t.JsonCW();
			if (t == null)
			{
				return Ok(new ResMsg(false, $"{typeof(T).Name}不存在",
					400));
			}

			TDto dto = _mapper.Map<TDto>(t);
			TDto afterGetOne = AfterGetOne(dto);
			return Ok(new ResMsg<TDto>(afterGetOne));
		}

		/// <summary>
		/// 多个id 获取多个
		/// </summary>
		/// <returns></returns>
		[HttpPost("ids")]
		//[Authorize("Permission")]
		public virtual async Task<IActionResult> GetByIds(
			[FromBody] long[] ids)
		{
			List<T> list = await _baseService.GetAllByIdsAsync(ids);
			if (list.Count != ids.Length)
			{
				return this.FailMsg("有个别没有查询到");
			}

			List<TDto> dtos = _mapper.Map<List<TDto>>(list);
			return this.SuccessMsg("成功", dtos);
		}

		/// <summary>
		/// 删除单个 
		/// </summary>
		/// <returns></returns>
		[HttpDelete("{id}")]
		//[Authorize("Permission")]
		public virtual async Task<IActionResult> DeleteOne(
			long id)
		{
			T t = await _baseService.GetOneByIdAsync(id);
			if (t == null)
			{
				return Ok(new ResMsg(false, $"{typeof(T).Name}不存在",
					400));
			}

			_baseService.TrueRemove(t);
			await _baseService.SaveAsync();
			return this.SuccessMsg("删除成功!");
		}

		/// <summary>
		/// 更新单个 
		/// </summary>
		/// <returns></returns>
		[HttpPut("{id}")]
		//[Authorize("Permission")]
		public virtual async Task<IActionResult> UpdateOne(
			long id, [FromBody] TUpdateDto updateDto)
		{
			if (!await _baseService.ExistByIdAsync(id))
			{
				this.FailMsg($"根据id查询{nameof(T)},不存在!");
			}

			T tEntity = await _baseService.GetOneByIdAsync(id);
			//entity转化updateDto -> updateDto值更新 到 updateDto
			//把 updateDto 映射回 entity
			_mapper.Map(updateDto, tEntity);
			_baseService.Update(tEntity);
			await _baseService.SaveAsync();
			TDto dto = _mapper.Map<TDto>(tEntity);
			return this.SuccessMsg("更新成功!", dto);
		}

		/// <summary>
		/// 添加一个
		/// </summary>
		/// <param name="dto"></param>
		/// <returns></returns>
		[HttpPost]
		//[Authorize("Permission")]
		public virtual async Task<IActionResult> AddOne(
			[FromBody] TAddDto dto)
		{
			dto.JsonCW();
			dto = SolveAddDto(dto);
			T tEntity = _mapper.Map<T>(dto);
			tEntity.JsonCW();
			_baseService.Add(tEntity);
			await _baseService.SaveAsync();
			TDto tDto = _mapper.Map<TDto>(tEntity);
			return this.SuccessMsg("添加成功!", tDto);
		}

		/// <summary>
		/// 处理AddDto
		/// </summary>
		/// <param name="dto"></param>
		/// <returns></returns>
		protected virtual TAddDto SolveAddDto(TAddDto dto)
		{
			return dto;
		}

		/// <summary>
		/// 查询单个后处理Dto
		/// </summary>
		/// <param name="dto"></param>
		/// <returns></returns>
		protected virtual TDto AfterGetOne(TDto dto)
		{
			return dto;
		}


		/// <summary>
		/// 获取所有 
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		// [Authorize("Permission")]
		public async Task<IActionResult> GetAll([FromQuery] TParam companyParameter)
		{
			ResMsg<PageRes<TDto>> pagesDto = await _baseService.GetPagesDto<TDto>(companyParameter);
			return Ok(pagesDto);
		}
	}
}